package org.dromara.iot.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.iot.domain.IotUpkeepInfo;
import org.dromara.iot.domain.bo.*;
import org.dromara.iot.domain.vo.*;
import org.dromara.iot.enums.BusinessCodeEnum;
import org.dromara.iot.enums.UpKeepEnum;
import org.dromara.iot.mapper.IotUpkeepInfoMapper;
import org.dromara.iot.service.*;
import org.dromara.system.domain.bo.SysCommunityBo;
import org.dromara.system.domain.vo.SysCommunityVo;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.service.ISysCommunityService;
import org.dromara.system.service.ISysUserService;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 电梯保养信息Service业务层处理
 *
 * @author lsl
 * @date 2024-06-14
 */
@RequiredArgsConstructor
@Service
public class IotUpkeepInfoServiceImpl implements IIotUpkeepInfoService {

    private final IotUpkeepInfoMapper baseMapper;

    private final IIotUpkeepRecordService upkeepRecordService;

    private final IIotUpkeepProjectRecordService projectRecordService;

    private final IIotUpkeepProjectService projectService;

    private final IIotElevatorService iotElevatorService;

    private final IIotUpkeepPlanService upkeepPlanService;

    private final ISysUserService userService;

    private final ISysCommunityService communityService;

    /**
     * 查询电梯保养信息
     */
    @Override
    public IotUpkeepInfoVo queryById(Long upkeepId) {
        IotUpkeepInfoVo iotUpkeepInfoVo = baseMapper.selectVoById(upkeepId);
        List<IotUpkeepProjectRecordVo> upkeepProjectRecordVoList = projectRecordService.queryListByUpkeepId(upkeepId);
        List<IotUpkeepRecordVo> upkeepRecordVoList = upkeepRecordService.queryListByUpkeepId(upkeepId);
        IotElevatorVo elevator = iotElevatorService.queryById(iotUpkeepInfoVo.getElevatorId());
        iotUpkeepInfoVo.setUpkeepProjectRecordVoList(upkeepProjectRecordVoList);
        iotUpkeepInfoVo.setUpkeepRecordVoList(upkeepRecordVoList);
        iotUpkeepInfoVo.setElevator(elevator);
        return iotUpkeepInfoVo;
    }

    /**
     * 查询电梯保养信息列表
     */
    @Override
    public TableDataInfo<IotUpkeepInfoVo> queryPageList(IotUpkeepInfoBo bo, PageQuery pageQuery) {
        QueryWrapper<IotUpkeepInfo> wrapper = Wrappers.query();
        wrapper.eq(StringUtils.isNotBlank(bo.getElevatorName()), " i.elevator_name", bo.getElevatorName());
        wrapper.eq(StringUtils.isNotBlank(bo.getUpkeepType()), "i.upkeep_type", bo.getUpkeepType());
        wrapper.eq(StringUtils.isNotBlank(bo.getUpkeepState()), "i.upkeep_state", bo.getUpkeepState());
        Page<IotUpkeepInfoVo> result = baseMapper.selectOwnVoPage(pageQuery.build(), wrapper);
        return TableDataInfo.build(result);
    }

    /**
     * 查询电梯保养信息列表
     */
    @Override
    public List<IotUpkeepInfoVo> queryList(IotUpkeepInfoBo bo) {
        LambdaQueryWrapper<IotUpkeepInfo> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<IotUpkeepInfo> buildQueryWrapper(IotUpkeepInfoBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<IotUpkeepInfo> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getElevatorId() != null, IotUpkeepInfo::getElevatorId, bo.getElevatorId());
        lqw.eq(bo.getTemplateId() != null, IotUpkeepInfo::getTemplateId, bo.getTemplateId());
        lqw.eq(StringUtils.isNotBlank(bo.getUpkeepCode()), IotUpkeepInfo::getUpkeepCode, bo.getUpkeepCode());
        lqw.like(StringUtils.isNotBlank(bo.getElevatorName()), IotUpkeepInfo::getElevatorName, bo.getElevatorName());
        lqw.eq(StringUtils.isNotBlank(bo.getIdentifyCode()), IotUpkeepInfo::getIdentifyCode, bo.getIdentifyCode());
        lqw.eq(StringUtils.isNotBlank(bo.getUseUnit()), IotUpkeepInfo::getUseUnit, bo.getUseUnit());
        lqw.eq(StringUtils.isNotBlank(bo.getMaintenanceUnit()), IotUpkeepInfo::getMaintenanceUnit, bo.getMaintenanceUnit());
        lqw.eq(StringUtils.isNotBlank(bo.getUpkeepType()), IotUpkeepInfo::getUpkeepType, bo.getUpkeepType());
        lqw.eq(StringUtils.isNotBlank(bo.getUpkeepState()), IotUpkeepInfo::getUpkeepState, bo.getUpkeepState());
        lqw.eq(StringUtils.isNotBlank(bo.getApplicant()), IotUpkeepInfo::getApplicant, bo.getApplicant());
        lqw.eq(bo.getOverTime() != null, IotUpkeepInfo::getOverTime, bo.getOverTime());
        lqw.eq(bo.getStartTime() != null, IotUpkeepInfo::getStartTime, bo.getStartTime());
        lqw.eq(StringUtils.isNotBlank(bo.getUpkeepDate()), IotUpkeepInfo::getUpkeepDate, bo.getUpkeepDate());
        lqw.eq(StringUtils.isNotBlank(bo.getLongitude()), IotUpkeepInfo::getLongitude, bo.getLongitude());
        lqw.eq(StringUtils.isNotBlank(bo.getLatitude()), IotUpkeepInfo::getLatitude, bo.getLatitude());
        lqw.eq(StringUtils.isNotBlank(bo.getRoomImg()), IotUpkeepInfo::getRoomImg, bo.getRoomImg());
        lqw.eq(StringUtils.isNotBlank(bo.getRoomRemark()), IotUpkeepInfo::getRoomRemark, bo.getRoomRemark());
        lqw.eq(StringUtils.isNotBlank(bo.getFloorImg()), IotUpkeepInfo::getFloorImg, bo.getFloorImg());
        lqw.eq(StringUtils.isNotBlank(bo.getFloorRemark()), IotUpkeepInfo::getFloorRemark, bo.getFloorRemark());
        lqw.eq(StringUtils.isNotBlank(bo.getCapsulesImg()), IotUpkeepInfo::getCapsulesImg, bo.getCapsulesImg());
        lqw.eq(StringUtils.isNotBlank(bo.getCapsulesRemark()), IotUpkeepInfo::getCapsulesRemark, bo.getCapsulesRemark());
        lqw.eq(StringUtils.isNotBlank(bo.getShaftImg()), IotUpkeepInfo::getShaftImg, bo.getShaftImg());
        lqw.eq(StringUtils.isNotBlank(bo.getShaftRemark()), IotUpkeepInfo::getShaftRemark, bo.getShaftRemark());
        lqw.eq(StringUtils.isNotBlank(bo.getReferUserSign()), IotUpkeepInfo::getReferUserSign, bo.getReferUserSign());
        lqw.eq(StringUtils.isNotBlank(bo.getAuditUserSign()), IotUpkeepInfo::getAuditUserSign, bo.getAuditUserSign());
        lqw.eq(StringUtils.isNotBlank(bo.getReferUser()), IotUpkeepInfo::getReferUser, bo.getReferUser());
        lqw.eq(StringUtils.isNotBlank(bo.getReferTime()), IotUpkeepInfo::getReferTime, bo.getReferTime());
        lqw.eq(StringUtils.isNotBlank(bo.getAuditUser()), IotUpkeepInfo::getAuditUser, bo.getAuditUser());
        lqw.eq(StringUtils.isNotBlank(bo.getAuditTime()), IotUpkeepInfo::getAuditTime, bo.getAuditTime());
        return lqw;
    }

    /**
     * 新增电梯保养信息
     */
    @Override
    public Boolean insertByBo(IotUpkeepInfoBo bo) {
        IotUpkeepInfo add = MapstructUtils.convert(bo, IotUpkeepInfo.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setUpkeepId(add.getUpkeepId());
        }
        return flag;
    }

    /**
     * 修改电梯保养信息
     */
    @Override
    public Boolean updateByBo(IotUpkeepInfoBo bo) {
        IotUpkeepInfo update = MapstructUtils.convert(bo, IotUpkeepInfo.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(IotUpkeepInfo entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除电梯保养信息
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 开始保养电梯
     *
     * @param upkeepId 主键
     */
    @Override
    public Boolean startUpkeep(Long upkeepId) {
        LoginUser user = LoginHelper.getLoginUser();
        IotUpkeepInfoVo upkeepInfoVo = this.queryById(upkeepId);
        if (!StringUtils.equals(UpKeepEnum.WAIT_UPKEEP.getCode(), upkeepInfoVo.getUpkeepState())) {
            throw new ServiceException("该保养已经开始或已完成");
        }
        if (CollectionUtil.isNotEmpty(upkeepInfoVo.getUpkeepRecordVoList()) && !upkeepInfoVo.getUpkeepRecordVoList().get(0).getReferUserId().equals(user.getUserId())) {
            throw new ServiceException("已有工程师接取该保养任务");
        }
        upkeepInfoVo.setApplicant(user.getNickname());
        upkeepInfoVo.setAvatar(user.getAvatar());
        upkeepInfoVo.setStartTime(DateUtil.date());
        baseMapper.updateById(BeanUtil.toBean(upkeepInfoVo, IotUpkeepInfo.class));

        //添加保养记录
        IotUpkeepRecordBo recordBo = new IotUpkeepRecordBo();
        recordBo.setUpkeepId(upkeepId);
        recordBo.setReferUserId(user.getUserId());
        recordBo.setCreateTime(DateUtil.date());
        upkeepRecordService.insertByBo(recordBo);
        return true;
    }

    /**
     * @param upkeepId    保养ID
     * @param projectType 项目类型
     * @return 保养详情
     */
    @Override
    public IotUpkeepInfoVo projectDetail(Long upkeepId, String projectType) {
        IotUpkeepInfoVo upkeepInfoVo = baseMapper.selectVoById(upkeepId);
        if (upkeepInfoVo == null) {
            return null;
        }
        IotElevatorVo iotElevatorVo = iotElevatorService.queryById(upkeepInfoVo.getElevatorId());
        upkeepInfoVo.setElevator(iotElevatorVo);
        //查询是否保存过项目保养记录
        IotUpkeepProjectRecordBo upkeepProjectRecordBo = new IotUpkeepProjectRecordBo();
        upkeepProjectRecordBo.setUpkeepId(upkeepId);
        upkeepProjectRecordBo.setProjectType(projectType);
        List<IotUpkeepProjectRecordVo> iotUpkeepProjectRecordVos = projectRecordService.queryList(upkeepProjectRecordBo);

        //查询模板是否含有
        IotUpkeepProjectBo projectBo = new IotUpkeepProjectBo();
        projectBo.setTemplateId(upkeepInfoVo.getTemplateId());
        projectBo.setProjectType(projectType);
        List<IotUpkeepProjectVo> iotUpkeepProjectVos = projectService.queryList(projectBo);

        if (CollUtil.isEmpty(iotUpkeepProjectRecordVos) && CollUtil.isNotEmpty(iotUpkeepProjectVos)) {
            List<IotUpkeepProjectRecordBo> iotUpkeepProjectRecordBos = BeanUtil.copyToList(iotUpkeepProjectVos, IotUpkeepProjectRecordBo.class);
            iotUpkeepProjectRecordBos.forEach(e -> e.setUpkeepId(upkeepId));
            projectRecordService.insertBatchByBo(iotUpkeepProjectRecordBos);
            iotUpkeepProjectRecordVos = projectRecordService.queryList(upkeepProjectRecordBo);
        }
        upkeepInfoVo.setUpkeepProjectRecordVoList(iotUpkeepProjectRecordVos);
        return upkeepInfoVo;
    }

    /**
     * 提交保养审核信息
     *
     * @param upkeepInfo 保养信息
     * @return 是否成功
     */
    @Override
    public Boolean submitUpkeepAuditInfo(IotUpkeepInfoBo upkeepInfo) {
        //查询提交人
        LoginUser referUser = LoginHelper.getLoginUser();
        IotUpkeepInfoVo iotUpkeepInfoVo = baseMapper.selectVoById(upkeepInfo.getUpkeepId());
        String type = upkeepInfo.getType();
        String auditStatus = upkeepInfo.getAuditStatus();
        String scoreMark = upkeepInfo.getScoreMark();
        String auditIdea = upkeepInfo.getAuditIdea();
        if (type.equals("1")) {
            if (StringUtils.isEmpty(upkeepInfo.getReferUserSign())) {
                throw new ServiceException("请签名后提交");
            }
            //修改保养计划最近一次保养时间
            IotUpkeepPlanVo upkeepPlanVo = upkeepPlanService.getByElevatorId(iotUpkeepInfoVo.getElevatorId());
            upkeepPlanVo.setRecentlyTime(new Date());
            //计算保养时长
            String datePoor = DateUtils.getDatePoor(iotUpkeepInfoVo.getStartTime(), DateUtil.date()).replaceAll("-", "");
            upkeepInfo.setUpkeepDate(datePoor);
            upkeepInfo.setUpkeepState(UpKeepEnum.WAIT_CONFIRM.getCode());
            //保存提交人信息
            upkeepInfo.setReferUser(referUser.getNickname());
            upkeepInfo.setReferTime(String.valueOf(DateUtil.date()));
            upkeepPlanService.updateByBo(BeanUtil.toBean(upkeepPlanVo, IotUpkeepPlanBo.class));

            //积分模块先注释掉
//            //添加积分
//            //获取上报故障积分
//            String score = integralConfigService.getScoreByType(referUser.getAttrId(), "4");
//            //避免输出科学计数法并去除末尾零
//            referUser.setOwnScore(NumberUtil.add(referUser.getOwnScore(), score).stripTrailingZeros().toPlainString());
//            userService.updateUserInfo(referUser);
//            //生成积分明细
//            IntegralDetail integralDetail = new IntegralDetail();
//            integralDetail.setDetailTitle("电梯保养");
//            integralDetail.setScoreType("0");
//            integralDetail.setChangeScore("+" + score);
//            integralDetail.setUserId(referUser.getUserId());
//            integralDetail.setCreateBy(referUser.getUserName());
//            integralDetail.setCreateTime(DateUtil.date());
//            integralDetailService.save(integralDetail);

        } else if (type.equals("2")) {
            //签名校验
            if (StringUtils.isEmpty(upkeepInfo.getAuditUserSign())) {
                throw new ServiceException("请签名后提交");
            }
            if (StringUtils.isEmpty(auditStatus)) {
                throw new ServiceException("审核状态不能为空");
            }

            //保存审核人信息
            upkeepInfo.setAuditUser(referUser.getNickname());
            upkeepInfo.setAuditTime(String.valueOf(DateUtil.date()));
            //状态：改已完成 3.已保养通过
            upkeepInfo.setUpkeepState(UpKeepEnum.FINISH.getCode());

        } else {
            throw new ServiceException("类型字段参数错误");
        }

        //编辑信息
        this.updateByBo(upkeepInfo);
        //修改保养记录 --提交给所属公司的 维保经理

        //查询维保经理 @TODO
        List<SysUserVo> keepManagerList = userService.selectUserListByDept(referUser.getDeptId());
        IotUpkeepRecordBo upkeepRecordByKeepManager = null;
        for (SysUserVo keepManager : keepManagerList) {
            IotUpkeepRecordVo iotUpkeepRecordVo = upkeepRecordService.selectAuditUserRecord(upkeepInfo.getUpkeepId(), keepManager.getUserId());
            if (ObjectUtil.isNotNull(iotUpkeepRecordVo) && keepManager.getUserId().equals(referUser.getUserId())) {
                iotUpkeepRecordVo.setAuditStatus(auditStatus);
                iotUpkeepRecordVo.setScoreMark(scoreMark);
                iotUpkeepRecordVo.setAuditIdea(auditIdea);
                upkeepRecordService.updateByBo(BeanUtil.toBean(iotUpkeepRecordVo, IotUpkeepRecordBo.class));
            } else if (ObjectUtil.isNull(iotUpkeepRecordVo)) {
                upkeepRecordByKeepManager = new IotUpkeepRecordBo();
                upkeepRecordByKeepManager.setUpkeepId(upkeepInfo.getUpkeepId());
                upkeepRecordByKeepManager.setAuditUserId(keepManager.getUserId());
                upkeepRecordByKeepManager.setAuditStatus("0");
                upkeepRecordByKeepManager.setCreateTime(DateUtil.date());
                upkeepRecordService.insertByBo(upkeepRecordByKeepManager);
            }
        }
        return true;
    }

    /**
     * 查询如果需要保养的电梯进行保养(定时器每天凌晨1点执行一次)
     * 查询保养计划 => 根据保养计划生成保养信息
     */
    @Override
    public void saveUpkeepBusinessInfo() {
        //查询系统全部电梯
        List<IotElevatorVo> elevatorList = iotElevatorService.queryList(new IotElevatorBo());
        //使用单位
        List<SysCommunityVo> sysCommunityVoList = communityService.queryList(new SysCommunityBo());
        List<IotUpkeepPlanVo> iotUpkeepPlanVoList = upkeepPlanService.queryList(new IotUpkeepPlanBo());

        for (IotElevatorVo elevatorInfo : elevatorList) {
            //查询对应的电梯保养计划
            IotUpkeepPlanVo elevatorPlan = iotUpkeepPlanVoList.stream().filter(e -> e.getElevatorId().equals(elevatorInfo.getElevatorId())).findFirst().orElse(null);
            if (ObjectUtil.isNull(elevatorPlan)) {
                continue;
            }
            //使用单位
            SysCommunityVo sysCommunityVo = sysCommunityVoList.stream().filter(e -> e.getCommunityId().equals(elevatorInfo.getCommunityId())).findFirst().orElse(new SysCommunityVo());
            //最近一次保养时间
            Date recentlyTime = elevatorPlan.getRecentlyTime();
            //首次保养时间
            Date firstUpkeepTime = elevatorPlan.getFirstUpkeepTime();
            //保养间隔时间
            Long upkeepInterval = elevatorPlan.getUpkeepInterval();
            //提醒天数
            Long remindDay = elevatorPlan.getRemindDay();

            if (ObjectUtil.isEmpty(recentlyTime)) {
                recentlyTime = firstUpkeepTime;
            }
            if (upkeepInterval > remindDay) {
                upkeepInterval = upkeepInterval - remindDay;
            } else {
                upkeepInterval = remindDay;
            }

            //获取保养时间
            Date upkeepDate = DateUtil.offsetDay(recentlyTime, Math.toIntExact(upkeepInterval));
            if (DateUtil.isSameDay(upkeepDate, DateUtil.date())) {
                //派发保养信息
                IotUpkeepInfo upkeepInfo = new IotUpkeepInfo();
                upkeepInfo.setElevatorId(elevatorInfo.getElevatorId());
                upkeepInfo.setTemplateId(elevatorPlan.getTemplateId() == null ? 30L : elevatorPlan.getTemplateId());
                upkeepInfo.setUpkeepCode(BusinessCodeEnum.MAINTENANCE.getBusinessCode());
                upkeepInfo.setElevatorName(elevatorInfo.getElevatorName());
                upkeepInfo.setIdentifyCode(elevatorInfo.getIdentifyCode());
                upkeepInfo.setUseUnit(sysCommunityVo.getName());
                //维保单位@TODO
                // upkeepInfo.setMaintenanceUnit(companyById.get(0).getCompanyName());
                upkeepInfo.setUpkeepType(elevatorPlan.getUpkeepType());
                upkeepInfo.setUpkeepState(UpKeepEnum.WAIT_UPKEEP.getCode());//保养状态
                //维保人
                String applicant = "";
                //List<SysUser> sysUserList = userService.selectUserListByAttrId(companyById.get(0).getCompanyId());
                //if (sysUserList != null && sysUserList.size() > 0) {
                //    for (SysUser sysUser : sysUserList) {
                //        String s = userService.selectUserRole(sysUser.getUserId());
                //        if (s.contains(BusinessConstants.KEEP_ENGINEER)) {
                //            applicant = applicant + sysUser.getUserId() + ",";
                //        }
                //    }
                //} else {
                //   continue;
                //  }
                upkeepInfo.setApplicant(applicant);
                //截止时间
                upkeepInfo.setOverTime(DateUtil.offsetDay(recentlyTime, Math.toIntExact(elevatorPlan.getUpkeepInterval())));
                // upkeepInfo.setLongitude(elevatorInfo.get());
                // pkeepInfo.setLatitude(elevatorInfo.getLatitude());
                baseMapper.insert(upkeepInfo);
            }
        }
    }
}
